/**
 *  Copyright 2013 Nate Dierk
 *
 *  COMP 590 -- Fall 2013
 */

#include "GContext0.cpp"

///////////////////////////////////////////////////////////
// Specialized GContext Implementations

class GContext_bmp : public GContext0 {
public:
  GContext_bmp(const GBitmap& bmp) : GContext0(bmp) { }
  ~GContext_bmp(){  }
};

class GContext_hw : public GContext0 {
public:  
  GContext_hw(const GBitmap& bmp) : GContext0(bmp) {}
  ~GContext_hw(){
    free(fBmp.fPixels); 
  }
};



///////////////////////////////////////////////////////////
// Context Validation Helpers
  
static bool isBmpValid(const GBitmap& bmp){
  return  !(bmp.fHeight   <= 0 || 
	    bmp.fWidth    <= 0 || 
	    bmp.fRowBytes < (bmp.fWidth * sizeof(GPixel)));
}

static bool isMemValid(const GBitmap& bmp){
  return bmp.fPixels != NULL;
}



///////////////////////////////////////////////////////////
// GContext Factories

GContext* GContext::Create(const GBitmap& bmp){
  if (isBmpValid(bmp) && isMemValid(bmp)){
    return new GContext_bmp(bmp);
  }
  return NULL;
}

GContext* GContext::Create(int width, int height){
  GBitmap bmp;
  bmp.fWidth = width;
  bmp.fHeight = height;
  bmp.fRowBytes = width * sizeof(GPixel);

  if (isBmpValid(bmp)){
    bmp.fPixels = (GPixel*) malloc(height * bmp.fRowBytes);
    
    if (isMemValid(bmp)){
      const GBitmap& pBmp = bmp;
      return new GContext_hw(pBmp);
    }
  } 
  return NULL;
}